/*
 * Copyright (C) 2009 Dimitrios C. Michalakos
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.cs.util.db.representation;

import com.cs.util.db.Database;
import com.cs.util.db.ResultSetMetaInfo;
import com.cs.util.db.ioc.IOController;
import com.cs.util.db.sql.Column;
import com.cs.util.db.sql.Filter;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * XhtmlForm can be used for creating a XHTML Form representation of a resultset or a table.
 * @author dimitris@jmike.gr
 */
public class XhtmlForm {

    private Database db;
    private ResultSet rs;
    private IOController[] ioc;
    private boolean isEmpty;
    private String title = "Another Xhtml Form Respresentation";//set default title
    private String cssLink = null;
    private String formAction = "";//set default formAction as "" (empty means this)

//    private int errorColumn = -1;
//    private String error = null;
//    private MultiValuedMap<String, String> formData = null;
    /**
     * Construncts a new XHTML From representation of the designated resultset.
     * @param db the database that the resultset derives from.
     * @param rs the resultset upon which the representation will be built.
     * @throws SQLException
     */
    public XhtmlForm(Database db, ResultSet rs) throws SQLException {
        this.db = db;
        this.rs = rs;
        rs.beforeFirst();
        this.isEmpty = !rs.next();
        ResultSetMetaInfo rsmi = db.getResultSetMetaInfo(rs);
        this.ioc = new IOController[rsmi.getColumnCount()];
        for (int i = 1; i <= rsmi.getColumnCount(); i++) {//iterate columns
            this.ioc[i] = db.getIOController(rsmi, i);
        }
    }

    public XhtmlForm(Database db, String table, Column[] columns, Filter[] filterBoundaries) throws SQLException {
        this.db = db;
        this.rs = null;
        this.isEmpty = true;
        ResultSetMetaInfo rsmi = db.getResultSetMetaInfo(table);
        this.ioc = new IOController[rsmi.getColumnCount()];
        for (int i = 1; i <= rsmi.getColumnCount(); i++) {//iterate columns
            this.ioc[i] = db.getIOController(rsmi, i);
        }
    }

    /**
     * Closes the internal resultset of this representation and clears meta data resources from memory.
     * @throws java.sql.SQLException
     */
    public void close() throws SQLException {
        db = null;
        if (rs != null) {
            rs.close();
        }
        ioc = null;
        isEmpty = false;
        title = "Another Xhtml Form Respresentation";
        cssLink = null;
        formAction = "";
    }

    /**
     * Sets the title of the Xhtml document.
     * @param title the title.
     * Title can be used for:
     * Defining a title in the browser toolbar.
     * Providing a title for the page when it is added to favorites.
     * Displaying a title for the page in search-engine results.
     * @return true if title has been set, false if not.
     */
    public boolean setTitle(String title) {
        if (title != null) {
            this.title = title;
            return true;
        } else {
            return false;
        }
    }

    /**
     * Sets the location of a linked stylesheet for the Xhtml document.
     * @param url the url of the css file.
     * @return true if stylesheet URL has been set, false if not.
     */
    public boolean setStylesheetURL(String url) {
        this.cssLink = url;
        return true;
    }

    /**
     * Sets the action attribute of the form.
     * Action is used to specify where to send the form-data when the form is submitted.
     * @param url the url that the data will be send to.
     * @return true if form action has been set, false if not.
     */
    public boolean setFormAction(String url) {
        if (url != null) {
            this.formAction = url;
            return true;
        } else {
            return false;
        }
    }

//    /**
//     * Sets an error for this form.
//     * @param error
//     */
//    public void setError(SuppliedDataException error) {
//        for (int i = 1; i <= rsmi.getColumnCount(); i++) {//iterate columns
//            try {
//                if (rsmi.getTable(i).equals("") && rsmi.getColumn(i).equals("")) {
//                    this.errorColumn = -1;
//                    this.error = null;
//                }
//            } catch (SQLException ex) {
//                /* ignore the error */
//            }
//        }
//    }

//    /**
//     * Sets the value of the input elements ot this form.
//     * @param formData
//     */
//    public void setFormData(MultiValuedMap<String, String> formData) {
//        this.formData = formData;
//    }
    /**
     * Returns this Representation as a String.
     * @return
     * @throws SQLException
     */
    public String display() throws SQLException {
        StringBuilder s = new StringBuilder();
        s.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD Xhtml 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
        s.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
        s.append("<head>");
        s.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
        if (cssLink != null) {
            s.append("<link rel=\"stylesheet\" href=\"" + cssLink + "\" type=\"text/css\" />");
        }
        s.append("<title>" + title + "</title>");
        s.append("</head>");
        s.append("<body>");
        s.append("<form action=\"" + formAction + "\" method=\"post\" enctype=\"multipart/form-data\">");
        for (int i = 0; i < ioc.length; i++) {//iterate io controllers
            s.append("<div>");
            s.append("<label for=\"" + ioc[i].getId() + "\">" + ioc[i].getLabel() + "</label>");
            s.append(ioc[i].getXhtmlFormElement(rs, isEmpty));
//            if (i == errorColumn) {
//                s.append("<span class=\"error\">");
//                s.append(error);
//                s.append("</span>");
//            }
            s.append("</div>");
        }
        s.append("<div>");
        s.append("<input type=\"file\" name=\"fileman\" />");
        s.append("</div>");
        s.append("<div>");
        s.append("<button type=\"submit\">Submit</button>");
        s.append("<button type=\"reset\">Reset</button>");
        s.append("</div>");
        s.append("</form>");
        s.append("</body>");
        s.append("</html>");
        return s.toString();
    }
}
